package com.linkgie.galaxyframework.crypto.context;

import com.linkgie.galaxyframework.crypto.Algorithm;
import com.linkgie.galaxyframework.crypto.HashCode;
import com.linkgie.galaxyframework.crypto.HashDigester;
import com.linkgie.galaxyframework.crypto.HashService;
import com.linkgie.galaxyframework.crypto.spi.DigestGenerator;
import com.linkgie.galaxyframework.crypto.spi.HashFuncSPI;
import com.linkgie.galaxyframework.crypto.spi.Hashbytes;

public class HashServiceImpl extends CryptoServiceBase<HashFuncSPI> implements HashService {

	public HashServiceImpl(HashFuncSPI innerService) {
		super(innerService);
	}

	@Override
	public HashCode hash(byte[] data) {
		Hashbytes hashBytes = INNSER_SERVICE.hash(data);
		return ENCODING.encode(ALGORITHM, hashBytes);
	}

	@Override
	public HashCode hash(byte[] data, int offset, int length) {
		Hashbytes hashBytes = INNSER_SERVICE.hash(data, offset, length);
		return ENCODING.encode(ALGORITHM, hashBytes);
	}
	
	@Override
	public byte[] hashInRaw(byte[] data) {
		return INNSER_SERVICE.hashInRaw(data);
	}
	
	@Override
	public byte[] hashInRaw(byte[] data, int offset, int length) {
		return INNSER_SERVICE.hashInRaw(data, offset, length);
	}
	
	@Override
	public byte[] hashInEncoded(byte[] data) {
		byte[] hashBytes = INNSER_SERVICE.hashInEncoded(data);
		return ENCODING.encodeToBytes(ALGORITHM, hashBytes);
	}
	
	@Override
	public byte[] hashInEncoded(byte[] data, int offset, int length) {
		byte[] hashBytes = INNSER_SERVICE.hashInEncoded(data, offset, length);
		return ENCODING.encodeToBytes(ALGORITHM, hashBytes);
	}

	@Override
	public HashDigester createDigester() {
		return new HashDigesterAdaptor(ALGORITHM, INNSER_SERVICE.createHashDigester());
	}

	private class HashDigesterAdaptor extends AbstractDigesterAdaptor<Hashbytes, HashCode> implements HashDigester {

		public HashDigesterAdaptor(Algorithm algorithm, DigestGenerator<Hashbytes> digestGenerator) {
			super(algorithm, digestGenerator);
		}

		@Override
		protected HashCode apply(Hashbytes digest) {
			return ENCODING.encode(ALGORITHM, digest);
		}

	}

}
